package com.yonyou.pmclouds.workflow.service;


import com.fasterxml.jackson.databind.JsonNode;
import com.yonyou.pmclouds.basecom.entity.SuperVO;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.workflow.util.WorkFlowConst;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import yonyou.bpm.rest.RuntimeService;
import yonyou.bpm.rest.exception.RestException;
import yonyou.bpm.rest.request.AssignInfo;
import yonyou.bpm.rest.request.RestVariable;

import java.util.List;

@Slf4j
@Component
public class ProcessRuntimeService {

    private RuntimeService getDefaultRuntimeService() throws BusinessException {
        return (RuntimeService) ProcessServiceFactory.getProcessService(ProcessServiceFactory.RUNTIME_SERVICE,
                RuntimeEnvironment.getLoginUserId(), RuntimeEnvironment.getTenantId());
    }

    /**
     * 流程启动
     */
    public JsonNode startProcessInstanceByKey(String processKey, SuperVO buziVO) throws BusinessException {
        List<RestVariable> variableList = ProcessVariableProcessor.getVariableList(buziVO);
        JsonNode resultJsonNode;
        try {
            Object result;
            long startTime = System.currentTimeMillis();
            if (variableList == null || variableList.size() == 0) {
                result = getDefaultRuntimeService().startProcessInstanceByKey(processKey, (String) buziVO.pkFiledValue());
            } else {
                result = getDefaultRuntimeService().startProcessInstanceByKey(processKey, (String) buziVO.pkFiledValue(), variableList);
            }
            log.debug("调用云审启动工作流耗时："+ (System.currentTimeMillis() - startTime));
            if (result == null)
                throw new BusinessException(WorkFlowConst.YS_NULL_RESP_MSG);
            resultJsonNode = (JsonNode) result;
            log.debug("流程启动返回值：" + resultJsonNode.toString());
        } catch (RestException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException("启动审批流失败（不包含指派信息）：" + e.getMessage());
        }
        return resultJsonNode;
    }

    /**
     * 流程启动
     *
     * @param processKey 流程模型key
     */
    public JsonNode startProcessInstanceWithAssign(String processKey, SuperVO buziVO, AssignInfo assignInfo) throws BusinessException {
        List<RestVariable> variableList = ProcessVariableProcessor.getVariableList(buziVO);

        JsonNode resultJsonNode;
        try {
            long startTime = System.currentTimeMillis();
            Object result;
            if (variableList == null || variableList.size() == 0) {
                result = getDefaultRuntimeService().startProcessInstanceByKey(processKey, (String) buziVO.pkFiledValue(), assignInfo);
            } else {
                result = getDefaultRuntimeService().startProcessInstanceByKeyAndTenantId(processKey, (String) buziVO.pkFiledValue(), variableList, RuntimeEnvironment.getTenantId(), assignInfo);
            }
            log.debug("调用云审启动工作流方法耗时（带指派信息）："+ (System.currentTimeMillis() - startTime));
            if (result == null)
                throw new BusinessException(WorkFlowConst.YS_NULL_RESP_MSG);
            resultJsonNode = (JsonNode) result;
            log.debug("流程启动返回值：" + resultJsonNode.toString());
        } catch (RestException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException("启动审批流（带指派信息）失败：" + e.getMessage());
        }
        return resultJsonNode;
    }

    /**
     * 驳回到某一个环节点
     * @param processInstanceId 流程实例ID
     * @param comment 评论
     * @param taskId 任务ID
     * @param activityId 环节点ID
     * @return 驳回结果
     */
    public JsonNode rejectToActivity(String processInstanceId,
                                     String comment,
                                     String taskId,
                                     String activityId) throws BusinessException {
        JsonNode jsonNode;
        try {
            // assigned为true，驳回时只给前面审批时指派的人员生成待办，否为环节点配置的全部人员
            Object resultObj = getDefaultRuntimeService().rejectToActivity(processInstanceId, activityId, comment, taskId, true);
            if (resultObj == null)
                throw new BusinessException(WorkFlowConst.YS_NULL_RESP_MSG);
            jsonNode = (JsonNode) resultObj;
        } catch (RestException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(e.getMessage());
        }

        return jsonNode;
    }

    public List<RestVariable> getVariableList(SuperVO businessVO) throws BusinessException {
        return ProcessVariableProcessor.getVariableList(businessVO);
    }
}
